#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "cJSON.h"
#include "cJSON.c"
#include "proxy.c"

#define BUFFER_SIZE 4096 * 1024

void write_msg(const char *filename, const char *content) {
    // 打开文件以进行写入，如果文件不存在则创建，如果存在则覆盖
    FILE *file = fopen(filename, "a+");

    if (file == NULL) {
        perror("Error opening file");
        exit(EXIT_FAILURE);
    }

    // 写入字符串到文件
    fprintf(file, "%s", content);

    // 关闭文件
    fclose(file);
}

void handle_connection(int client_socket) {
    char buffer[4096];
    ssize_t bytes_received;

    // Read the client's request
    bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
    if (bytes_received < 0) {
        printf("Error reading from client");
        close(client_socket);
        return;
    }

    char *method = strtok(buffer, " ");
    char *url = strtok(NULL, " ");
    printf("URL %s = %s \n", method, url);
   

    // Print the client's request
    printf("Received HTTP Request 000: %.*s $$$ \n", (int)bytes_received, buffer);
    // printf("%.*s", (int)bytes_received, buffer);

    // Send a simple response

    cJSON* root = NULL;
	char* out = NULL;
	root = cJSON_CreateObject();
	cJSON_AddStringToObject(root, "name", "张三");//添加字符串键值对
	cJSON_AddNumberToObject(root , "age", 9);//添加数字键值对
	out = cJSON_PrintUnformatted(root);//转成带格式的字符串，含空格和换行等格式
    printf("%s\n",out);

    char* response;
    asprintf(&response, "HTTP/1.1 200 OK\r\nContent-Length: %zu \r\n\r\n%s", strlen(out), out);

    // char* response = "HTTP/1.1 200 OK\r\nContent-Length: 16\r\n\r\nHello World 123!";
    // char* response = "{\"aa\":12323}";
    printf(" Start To send response 1111 ");
    send(client_socket, response, strlen(response), 0);
    printf(" Start To send response 2222 ");

    // Close the client socket
    close(client_socket);
}

void handle_direct_connection(int client_socket, const char* target_host, int target_port) {
    // 解析域名的IP地址
    struct addrinfo hints, *result; 
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    int status = getaddrinfo(target_host, NULL, &hints, &result);
    if (status != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        return;
    }

    // 创建套接字连接目标服务器
    printf("handle_direct_connection ... \n");
    int target_socket = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in target_addr;
    target_addr.sin_family = AF_INET;
    target_addr.sin_port = htons(target_port);
    printf("handle_direct_connection 000 \n");
    inet_pton(AF_INET, target_host, &target_addr.sin_addr);

    printf("handle_direct_connection 111 \n");
    int sock_fd = -1;
    // sock_fd = socket_connect(target_host, target_port, 5);
    sock_fd = connect(target_socket, (struct sockaddr*)&target_addr, sizeof(target_addr));
    // if (connect(target_socket, (struct sockaddr*)&target_addr, sizeof(target_addr)) == -1) {
    if (sock_fd < 0) {
        printf("Error connecting to target server - %d \n", sock_fd);
        close(client_socket);
        return;
    }

    // 读取客户端请求
    printf("handle_direct_connection 222 \n");
    char buffer_client[BUFFER_SIZE];
    // char buffer_target[BUFFER_SIZE];
    ssize_t bytes_received = recv(client_socket, buffer_client, sizeof(buffer_client), 0);
    if (bytes_received < 0) {
        printf("Error reading from client  \n");
        close(client_socket);
        close(target_socket);
        return;
    }

    // 将客户端请求发送到目标服务器
    printf("handle_direct_connection 333 \n");
    ssize_t bytes_sent = send(target_socket, buffer_client, bytes_received, 0);
    if (bytes_sent < 0) {
        printf("Error sending to target server  \n");
        close(client_socket);
        close(target_socket);
        return;
    }

    // 从目标服务器读取响应
    printf("%s \n", buffer_client);
    printf("handle_direct_connection 444 \n");
    bytes_received = recv(target_socket, buffer_client, sizeof(buffer_client), 0);
    if (bytes_received < 0) {
        printf("Error reading from target server  \n");
        close(client_socket);
        close(target_socket);
        return;
    }

    // 将响应发送回客户端
    printf("handle_direct_connection 555 :: %zd \n", bytes_received);
    bytes_sent = send(client_socket, buffer_client, bytes_received, 0);
    if (bytes_sent < 0) {
        printf("Error sending to client  \n");
    }

    // 关闭套接字
    printf("%s \n", buffer_client);
    printf("handle_direct_connection 666 \n");
    printf("%zd \n", bytes_sent);
    close(client_socket);
    close(target_socket);
}


void start_proxy(int port) {
    int server_socket, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);

    // 创建服务器套接字
    server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 配置服务器地址结构
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    // 将地址结构绑定到套接字
    bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 监听套接字
    if (listen(server_socket, 5) == 0) {
        printf("Proxy server listening 1233..\n");
    } else {
        perror("Error in listening");
        exit(EXIT_FAILURE);
    }

    while (1) {
        // 接受连接
        printf("Start accepting connection 11 %u \n", addr_len);
        client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_len);
        printf("Start accepting connection 22 %d \n", client_socket);
        if (client_socket < 0) {
            perror("Error accepting connection");
            continue;
        }

        // 处理直接连接
        printf("Start For handle_connection ... \n");
        // handle_connection(client_socket);
        // handle_connection1(client_socket);
        handle_direct_connection(client_socket, "admin-api.hdedu.local", 80);
    }
}

int main() {
    start_proxy(8888);
    // return 0;
}
